package org.ehe.business.bom.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.ehe.business.bom.domain.*;
import org.ehe.business.bom.domain.bo.BomPageBo;
import org.ehe.business.bom.domain.dto.*;
import org.ehe.business.bom.domain.vo.BomPageVO;
import org.ehe.business.bom.service.*;
import org.ehe.business.drawing.domain.DesignDrawing;
import org.ehe.business.drawing.domain.DesignDrawingFiles;
import org.ehe.business.drawing.domain.DesignDrawingSite;
import org.ehe.business.drawing.domain.vo.DesignDrawingVO;
import org.ehe.business.drawing.mapper.DesignDrawingMapper;
import org.ehe.business.drawing.service.DesignDrawingFilesService;
import org.ehe.business.supplier.domain.dto.SupplierUpdate;
import org.ehe.business.timeout.contants.BizTypeConstant;
import org.ehe.business.timeout.mapper.TimeoutConfigMapper;
import org.ehe.common.core.constant.RoleKeyConstants;
import org.ehe.common.core.constant.StatusEnum;
import org.ehe.common.core.enums.BomTypeEnum;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.common.sse.dto.SseMessageDto;
import org.ehe.common.sse.utils.SseMessageUtils;
import org.ehe.erp.domain.product.vo.ErpProductCategoryVo;
import org.ehe.erp.domain.product.vo.ErpProductVo;
import org.ehe.erp.service.product.IErpProductCategoryService;
import org.ehe.erp.service.product.IErpProductService;
import org.ehe.system.domain.vo.SysOssVo;
import org.ehe.system.service.ISysOssService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * BOM业务流程服务实现类
 * @author :zhangnn
 * @className :BomBusinessServiceImpl
 * @description: 整合各个子服务，实现完整的BOM管理业务流程
 * @date 2025-07-30 14:27:49
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BomBusinessServiceImpl implements BomBusinessService {
    private final BomMasterService bomMasterService;
    private final BomVersionService bomVersionService;
    private final BomStructureService bomStructureService;
    private final BomChangeLogService bomChangeLogService;
    private final BomProjectRelationService bomProjectRelationService;
    private final DesignDrawingMapper designDrawingMapper;
    private final ScheduledExecutorService scheduledExecutorService;
    private final IErpProductCategoryService categoryService;
    private final IErpProductService productService;
    private final DesignDrawingFilesService designDrawingFilesService;
    private final ISysOssService ossService;
    private final TimeoutConfigMapper timeoutConfigMapper;

    /**
     * 分页列表
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public TableDataInfo<BomPageVO> pageBoms(BomPageBo bo, PageQuery pageQuery) {
        // 1. 构建BOM主表查询条件
        LambdaQueryWrapper<BomMaster> bomWrapper = Wrappers.lambdaQuery();
        bomWrapper.like(StringUtils.isNotBlank(bo.getBomCode()), BomMaster::getBomCode, bo.getBomCode())
            .like(StringUtils.isNotBlank(bo.getBomName()), BomMaster::getBomName, bo.getBomName())
            .eq(Objects.nonNull(bo.getProjectId()), BomMaster::getProjectId, bo.getProjectId())
            .like(StringUtils.isNotBlank(bo.getProjectName()), BomMaster::getProjectName, bo.getProjectName())
            .like(StringUtils.isNotBlank(bo.getSolutionName()), BomMaster::getSolutionName, bo.getSolutionName())
            .eq(Objects.nonNull(bo.getBomType()), BomMaster::getBomType, bo.getBomType())
            .eq(Objects.nonNull(bo.getStatus()), BomMaster::getStatus, bo.getStatus())
            .eq(Objects.nonNull(bo.getId()), BomMaster::getId, bo.getId())
            .orderByDesc(BomMaster::getCreateTime);

        // 如果不是管理员角色，则只能看到自己创建的BOM
        if (!(StpUtil.hasRoleOr(RoleKeyConstants.getAdminRoles().toArray(new String[0])))) {
            // 获取当前登录用户名
            String currentUsername = LoginHelper.getUsername();
            // 添加创建者过滤条件
            bomWrapper.eq(BomMaster::getCreateBy, currentUsername);
        }

        // 2. 先查询BOM主表数据（不分页，因为要展平显示）
        Page<BomMaster> page = bomMasterService.page(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), bomWrapper);

        // 3. 获取BOM ID列表
        List<Long> bomIds = page.getRecords().stream().map(BomMaster::getId).collect(Collectors.toList());

        // 4. 查询项目关联信息
        LambdaQueryWrapper<BomProjectRelation> relationWrapper = Wrappers.lambdaQuery();
        relationWrapper.in(CollectionUtils.isNotEmpty(bomIds),BomProjectRelation::getBomId, bomIds)
            .eq(BomProjectRelation::getRelationType, 1); // 主要BOM
        List<BomProjectRelation> projectRelations = bomProjectRelationService.list(relationWrapper);

        Map<Long, String> bomProjectMap = projectRelations.stream()
                .collect(Collectors.toMap(BomProjectRelation::getBomId, BomProjectRelation::getProjectName, (v1, v2) -> v1));


        // 5. 查询BOM版本信息
        LambdaQueryWrapper<BomVersion> versionWrapper = Wrappers.lambdaQuery();
        versionWrapper.in(CollectionUtils.isNotEmpty(bomIds),BomVersion::getBomId, bomIds);
            //.eq(BomVersion::getStatus, 2); // 已发布版本
        List<BomVersion> bomVersions = bomVersionService.list(versionWrapper);
        Map<Long, BomVersion> bomVersionMap = bomVersions.stream()
                .collect(Collectors.toMap(BomVersion::getBomId, Function.identity(), (v1, v2) -> v1));


        // 6. 查询BOM结构明细
        Map<Long, List<BomStructure>> bomStructuresMap = new HashMap<>();
        if(null != bo.getId()){
            List<Long> versionIds = bomVersions.stream().map(BomVersion::getId).collect(Collectors.toList());

            if (CollUtil.isNotEmpty(versionIds)) {
                LambdaQueryWrapper<BomStructure> structureWrapper = Wrappers.lambdaQuery();
                structureWrapper.in(BomStructure::getBomVersionId, versionIds)
                    .orderByAsc(BomStructure::getLevelNo)
                    .orderByAsc(BomStructure::getSeqNo);
                List<BomStructure> bomStructures = bomStructureService.list(structureWrapper);
                // 按版本ID分组存储结构明细
                bomStructuresMap = bomStructures.stream()
                    .collect(Collectors.groupingBy(BomStructure::getBomVersionId));
            }
        }
        // 7. 组装VO数据（每个BomMaster对应一个VO，包含其所有明细项）
        List<BomPageVO> voList = new ArrayList<>();
        for (BomMaster bomMaster : page.getRecords()) {
            BomVersion bomVersion = bomVersionMap.get(bomMaster.getId());
            if (bomVersion == null) continue;

            String projectName = bomProjectMap.get(bomMaster.getId());
            List<BomStructure> structures = bomStructuresMap.getOrDefault(bomVersion.getId(), Collections.emptyList());
            for (BomStructure structure : structures) {
                ErpProductVo erpProductVo = productService.queryById(structure.getItemId());
                if(Objects.nonNull(erpProductVo)) {
                    structure.setCustomizeCode(erpProductVo.getCustomizeCode());
                    ErpProductCategoryVo categoryVo = categoryService.selectByCode(erpProductVo.getCategoryCode());
                    structure.setCategoryCode(categoryVo.getCode());
                    structure.setItemTypeName(categoryVo.getName());

                    //类别
                    ErpProductCategoryVo top = getTopParent(Long.valueOf(structure.getItemType()));
                    if(Objects.nonNull(top)){
                        structure.setItemTypeName(top.getName());
                    }
                }
                //构建全码、单位名称等
                ErpProductVo erpProductVo1 = productService.buildProductVO(erpProductVo);
                structure.setFullCode(erpProductVo1.getFullCode());
                structure.setFullName(erpProductVo1.getFullName());
                structure.setUnitName(erpProductVo1.getUnitName());
            }
            // 创建主VO对象（包含明细列表）
            BomPageVO masterVo = createBomMasterVO(bomMaster, projectName, bomVersion);
            masterVo.setStructureList(structures);

            //获取关联设计稿信息
            DesignDrawingVO drawingVO = designDrawingMapper.selectVoById(bomMaster.getDrawId());
            if(Objects.nonNull(drawingVO)){
                masterVo.setDrawCode(drawingVO.getDrawCode());
                masterVo.setDrawName(drawingVO.getDrawName());
                masterVo.setDrawNo(drawingVO.getDrawNo());
            }
            voList.add(masterVo);
        }

        // 8. 构建分页结果（使用BomMaster的分页数据）
        Page<BomPageVO> resultPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        resultPage.setRecords(voList);
        return TableDataInfo.build(resultPage);
    }

    public ErpProductCategoryVo getTopParent(Long currentId) {
        ErpProductCategoryVo current = categoryService.queryById(currentId);
        // 循环查询父节点，直到parent_id为0（根节点）
        if (current == null) {
            return null;
        }
        Long parentId = current.getParentId();
        // 循环向上找父节点，直到parent_id为0
        while (parentId != 0) {
            ErpProductCategoryVo parent = categoryService.queryById(parentId);
            if (parent == null) {
                break;
            }
            current = parent;
            parentId = current.getParentId();
        }
        // 如果最终找到的节点parent_id为0，说明是根节点，返回它；否则返回null（理论上正常数据不会出现这种情况）
        return current.getParentId() == 0 ? current : null;
    }

    /**
     * 详情接口
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public BomPageVO detail(BomPageBo bo, PageQuery pageQuery) {
        TableDataInfo<BomPageVO> tableDataInfo = this.pageBoms(bo,pageQuery);
        BomPageVO bomPageVO = tableDataInfo.getRows().get(0);
        Long drawId = bomPageVO.getDrawId();
        DesignDrawingVO drawingVO = designDrawingMapper.selectVoById(drawId);
        if (Objects.nonNull(drawingVO)) {
            // 查询当前图纸关联的文件列表
            List<DesignDrawingFiles> files = designDrawingFilesService.list(
                new LambdaQueryWrapper<DesignDrawingFiles>().eq(DesignDrawingFiles::getDrawId, drawId)
            );
            if (CollUtil.isNotEmpty(files)) {
                List<SysOssVo> ossVoList = new ArrayList<>();

                // 遍历每个文件，单独查询并设置其关联的附件
                for (DesignDrawingFiles file : files) {
                    Long attachmentId = file.getAttachmentId();
                    if (attachmentId != null) {
                        SysOssVo ossVo = ossService.getById(attachmentId);
                        ossVoList.add(ossVo);
                    }
                    file.setOssVoList(ossVoList);
                }
            }
            drawingVO.setFiles(files);
        }
        bomPageVO.setDrawingVO(drawingVO);
        return bomPageVO;
    }

    /**
     * master 转 vo
     * @param master
     * @param projectName
     * @param version
     * @return
     */
    private BomPageVO createBomMasterVO(BomMaster master, String projectName, BomVersion version) {
        BomPageVO vo = new BomPageVO();
        vo.setId(master.getId());
        vo.setDrawId(master.getDrawId());
        vo.setBomId(master.getId());
        vo.setBomCode(master.getBomCode());
        vo.setBomName(master.getBomName());
        vo.setBomType(master.getBomType());
        vo.setBomTypeName(BomTypeEnum.getValueByCode(String.valueOf(master.getBomType())));
        vo.setStatus(master.getStatus());
        vo.setApproveStatus(master.getApproveStatus());
        vo.setStatusName(bomVersionService.getVersionStatusName(vo.getStatus()));
        vo.setProjectId(master.getProjectId());
        vo.setProjectName(projectName);
        vo.setSolutionId(master.getSolutionId());
        vo.setSolutionName(master.getSolutionName());
        vo.setCurrentVersion(version.getVersionName());
        vo.setRemark(master.getRemark());
        vo.setEffectiveDate(master.getEffectiveDate());
        vo.setExpireDate(master.getExpireDate());

        vo.setIsOverdue(master.getIsOverdue());
        vo.setIsOverdueEndTime(master.getIsOverdueEndTime());
        vo.setTaskDeadline(master.getTaskDeadline());
        vo.setEstimatedHours(master.getEstimatedHours());
        vo.setIsTaskTimeout(master.getIsTaskTimeout());
        return vo;
    }

    /**
     * 阶段1：项目启动 & BOM创建 (设计BOM - EBOM)
     */
    @Transactional
    public BomCreationResult saveOrUpdateDesignBom(BomCreationRequest request) {

        boolean isUpdate = request.getId() != null;
        String operation = isUpdate ? "更新" : "创建";
        log.info("{}设计BOM: bomId={}, bomCode={}, bomName={}",
            operation, request.getId(), request.getBomCode(), request.getBomName());

        request.setIsOverdue("0");
        int hours = timeoutConfigMapper.getTimeByBizType(BizTypeConstant.BOM);
        request.setIsOverdueEndTime(LocalDateTime.now().plusHours(hours));

        try {
            BomMaster bomMaster;
            BomVersion currentVersion;

            String changeReason = "";
            if (isUpdate) {
                // 编辑模式
                //request.setCreateBy(LoginHelper.getUsername());
                request.setUpdateBy(LoginHelper.getUsername());
                bomMaster = bomMasterService.updateBomMaster(request);
                currentVersion = bomVersionService.getDraftVersion(bomMaster.getId());
                changeReason = "编辑变更";
            } else {
                // 新增模式
                request.setCreateBy(LoginHelper.getUsername());
                bomMaster = bomMasterService.createBomMaster(request);
                currentVersion = bomVersionService.getDraftVersion(bomMaster.getId());
                changeReason = "初始版本";
            }
            if (currentVersion == null) {
                // 如果没有草稿版本，创建新版本
                currentVersion = bomVersionService.createNewVersion(bomMaster.getId(), changeReason,"");
            }


            // 更新或新增项目关联关系
            bomProjectRelationService.upsertProjectRelation(bomMaster, request);

            // 处理结构数据
            if (request.getStructureItems() != null && !request.getStructureItems().isEmpty()) {
                if (isUpdate) {
                    // 编辑模式：先清除现有结构，再添加新结构
                    bomStructureService.clearVersionStructures(currentVersion.getId());
                }
                List<BomStructure> structureItems = request.getStructureItems();
                BomVersion finalCurrentVersion = currentVersion;
                structureItems.forEach(structure->{
                    structure.setBomVersionId(finalCurrentVersion.getId());
                    bomStructureService.addBomStructureItem(structure);
                });
            }

            // 重新计算成本
            BigDecimal totalCost = bomStructureService.calculateBomTotalCost(currentVersion.getId());
            request.setId(bomMaster.getId());
            request.setCreateBy(bomMaster.getCreateBy());

            BomCreationResult result = new BomCreationResult();
            result.setBomName(bomMaster.getBomName());
            result.setCreateBy(bomMaster.getCreateBy());

            result.setBomMaster(bomMaster);
            result.setBomVersion(currentVersion);
            result.setTotalCost(totalCost);
            result.setSuccess(true);
            result.setMessage(operation + "设计BOM成功");

            log.info("{}设计BOM成功: bomId={}, totalCost={}", operation, bomMaster.getId(), totalCost);
            return result;

        } catch (Exception e) {
            log.error("{}设计BOM失败", operation, e);
            BomCreationResult result = new BomCreationResult();
            result.setSuccess(false);
            result.setMessage(operation + "失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 提交EBOM审批
     */
    @Transactional
    public BomMaster submitEbomForApproval(Long bomId,Long days,Long workflowInstanceId) {
        log.info("提交EBOM审批: bomId={}", bomId);

        // 验证BOM完整性
        BomVersion currentVersion = bomVersionService.getDraftVersion(bomId);
        if (currentVersion == null) {
            throw new RuntimeException("找不到草稿版本");
        }

        List<String> issues = bomStructureService.validateBomStructureIntegrity(currentVersion.getId());
        if (!issues.isEmpty()) {
            throw new RuntimeException("BOM结构验证失败: " + String.join(", ", issues));
        }
        // 提交审批
        BomMaster bomMaster = bomMasterService.submitForApproval(bomId, days,workflowInstanceId);
        return bomMaster;

    }

    /**
     * 审批通过
     * @param bomId
     * @param userId
     * @param code
     */
    @Override
    public BomMaster approveBom(Long bomId, Long userId, String code) {
       return bomMasterService.approveBom(bomId,userId,code);
    }

    /**
     * 审批拒绝
     * @param bomId
     * @param rejectReason
     */
    @Override
    public BomMaster rejectBom(Long bomId, String rejectReason) {
       return bomMasterService.rejectBom(bomId,rejectReason);
    }

    /**
     * 阶段2：BOM细化 & 转换 (设计BOM -> 制造BOM)
     */
    @Transactional
    public BomConversionResult convertEbomToMbom(BomConversionRequest request) {
        log.info("开始BOM转换: sourceBomId={}, targetBomType={}", request.getSourceBomId(), request.getTargetBomType());

        try {
            // 1. 基于EBOM创建新的MBOM
            BomMaster newBom = bomMasterService.createBomFromExisting(
                request.getSourceBomId(),
                request.getTargetBomType(),
                request.getNewBomCode(),
                request.getNewBomName()
            );

            // 2. 获取新创建的版本
            BomVersion newVersion = bomVersionService.getDraftVersion(newBom.getId());

            // 3. 根据工艺要求调整BOM结构
            if (request.getStructureAdjustments() != null && !request.getStructureAdjustments().isEmpty()) {
                applyStructureAdjustments(newVersion.getId(), request.getStructureAdjustments());
            }

            // 4. 添加工艺辅料、消耗品
            if (request.getAdditionalItems() != null && !request.getAdditionalItems().isEmpty()) {
                addAdditionalItems(newVersion.getId(), request.getAdditionalItems());
            }

            // 5. 更新供应商信息
            if (request.getSupplierUpdates() != null && !request.getSupplierUpdates().isEmpty()) {
                updateSupplierInformation(newVersion.getId(), request.getSupplierUpdates());
            }

            // 6. 重新计算成本
            BigDecimal totalCost = bomStructureService.calculateBomTotalCost(newVersion.getId());

            BomConversionResult result = new BomConversionResult();
            result.setNewBomMaster(newBom);
            result.setNewBomVersion(newVersion);
            result.setTotalCost(totalCost);
            result.setSuccess(true);
            result.setMessage("BOM转换成功");

            log.info("BOM转换成功: newBomId={}, totalCost={}", newBom.getId(), totalCost);
            return result;

        } catch (Exception e) {
            log.error("BOM转换失败", e);
            BomConversionResult result = new BomConversionResult();
            result.setSuccess(false);
            result.setMessage("转换失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 阶段3+：BOM变更管理
     */
    @Transactional
    public BomChangeResult submitBomChange(BomChangeRequest request) {
        log.info("提交BOM变更: bomId={}, changeType={}", request.getBomId(), request.getChangeType());

        try {
            // 1. 创建变更记录
            BomChangeLog changeLog = new BomChangeLog();
            changeLog.setBomId(request.getBomId());
            changeLog.setChangeType(request.getChangeType());
            changeLog.setChangeObject(request.getChangeObject());
            changeLog.setOldVersionId(request.getOldVersionId());
            changeLog.setChangeContent(request.getChangeContent());
            changeLog.setChangeReason(request.getChangeReason());
            changeLog.setImpactAnalysis(request.getImpactAnalysis());
            changeLog.setChangeApplicantId(request.getChangeApplicantId());
            changeLog.setChangeApplicantName(request.getChangeApplicantName());

            changeLog = bomChangeLogService.createChangeRequest(changeLog);

            // 2. 生成影响分析
            if (changeLog.getImpactAnalysis() == null || changeLog.getImpactAnalysis().isEmpty()) {
                String impactAnalysis = bomChangeLogService.generateImpactAnalysis(changeLog);
                changeLog.setImpactAnalysis(impactAnalysis);
                bomChangeLogService.updateById(changeLog);
            }

            BomChangeResult result = new BomChangeResult();
            result.setChangeLog(changeLog);
            result.setSuccess(true);
            result.setMessage("变更请求提交成功");

            log.info("BOM变更请求提交成功: changeLogId={}", changeLog.getId());
            return result;

        } catch (Exception e) {
            log.error("BOM变更请求提交失败", e);
            BomChangeResult result = new BomChangeResult();
            result.setSuccess(false);
            result.setMessage("提交失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 实施BOM变更
     */
    @Transactional
    public void implementBomChange(Long changeLogId) {
        log.info("实施BOM变更: changeLogId={}", changeLogId);

        // 1. 实施变更
        bomChangeLogService.implementChange(changeLogId);

        // 2. 更新相关缓存或触发其他业务流程
        // 通知MRP重新计算、更新采购计划等
        triggerPostChangeActions(changeLogId);
    }

    /**
     * 生成MRP物料需求计划
     */
    public MrpResult generateMrp(MrpRequest request) {
        log.info("生成MRP: bomId={}, productionQuantity={}", request.getBomId(), request.getProductionQuantity());

        try {
            // 1. 获取有效的制造BOM版本
            BomVersion bomVersion = bomVersionService.getCurrentVersion(request.getBomId());
            if (bomVersion == null) {
                throw new RuntimeException("找不到有效的BOM版本");
            }

            // 2. 展开BOM结构
            List<BomStructure> bomStructures = bomStructureService.getBomMaterialList(bomVersion.getId());

            // 3. 计算物料需求
            List<MaterialRequirement> requirements = new ArrayList<>();

            for (BomStructure structure : bomStructures) {
                MaterialRequirement requirement = new MaterialRequirement();
                requirement.setItemId(structure.getItemId());
                requirement.setItemCode(structure.getItemCode());
                requirement.setItemName(structure.getItemName());
                requirement.setUnit(structure.getUnit());

                // 计算净需求量（考虑损耗率）
                BigDecimal scrapRate = structure.getScrapRate() != null ? structure.getScrapRate() : BigDecimal.ZERO;
                BigDecimal actualQuantity = structure.getQuantity()
                    .multiply(request.getProductionQuantity())
                    .multiply(BigDecimal.ONE.add(scrapRate.divide(new BigDecimal("100"))));

                requirement.setGrossRequirement(actualQuantity);

                // 这里应该查询库存和在途订单，计算净需求
                // 简化处理，直接使用毛需求
                requirement.setNetRequirement(actualQuantity);
                requirement.setSupplierId(structure.getSupplierId());
                requirement.setSupplierName(structure.getSupplierName());
                requirement.setLeadTime(structure.getLeadTime());

                // 计算需求日期
                Calendar cal = Calendar.getInstance();
                cal.setTime(request.getRequiredDate());
                if (structure.getLeadTime() != null) {
                    cal.add(Calendar.DAY_OF_MONTH, -structure.getLeadTime());
                }
                requirement.setRequiredDate(cal.getTime());

                requirements.add(requirement);
            }

            MrpResult result = new MrpResult();
            result.setRequirements(requirements);
            result.setSuccess(true);
            result.setMessage("MRP生成成功");

            log.info("MRP生成成功，共{}种物料", requirements.size());
            return result;

        } catch (Exception e) {
            log.error("MRP生成失败", e);
            MrpResult result = new MrpResult();
            result.setSuccess(false);
            result.setMessage("生成失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 获取BOM完整信息（用于展示）
     */
    public BomCompleteInfo getBomCompleteInfo(Long bomId) {
        log.info("获取BOM完整信息: bomId={}", bomId);

        BomCompleteInfo info = new BomCompleteInfo();

        // 1. BOM基本信息
        BomMaster bomMaster = bomMasterService.getById(bomId);
        info.setBomMaster(bomMaster);

        // 2. 当前版本信息
        BomVersion currentVersion = bomVersionService.getCurrentVersion(bomId);
        info.setCurrentVersion(currentVersion);

        // 3. 版本历史
        List<BomVersion> versionHistory = bomVersionService.getVersionHistory(bomId);
        info.setVersionHistory(versionHistory);

        // 4. BOM结构树
        if (currentVersion != null) {
            List<BomStructure> structureTree = bomStructureService.getBomStructureTree(currentVersion.getId());
            info.setStructureTree(structureTree);

            // 5. 成本信息
            BigDecimal totalCost = bomStructureService.calculateBomTotalCost(currentVersion.getId());
            info.setTotalCost(totalCost);

            // 6. 关键物料
            List<BomStructure> keyItems = bomStructureService.getKeyItems(currentVersion.getId());
            info.setKeyItems(keyItems);
        }

        // 7. 项目关联信息
        List<BomProjectRelation> projectRelations = bomProjectRelationService.getRelationsByBomId(bomId);
        info.setProjectRelations(projectRelations);

        // 8. 变更记录
        List<BomChangeLog> changeLogs = bomChangeLogService.getChangeLogsByBomId(bomId);
        info.setChangeLogs(changeLogs);

        // 9. 变更统计
        Map<String, Object> changeStatistics = bomChangeLogService.getChangeStatistics(bomId);
        info.setChangeStatistics(changeStatistics);

        return info;
    }

    /**
     * 项目结束时批量处理BOM
     */
    @Transactional
    public void handleProjectClosing(Long projectId, Date projectEndDate) {
        log.info("处理项目结束: projectId={}, endDate={}", projectId, projectEndDate);

        // 1. 获取项目相关的所有BOM
        List<BomMaster> projectBoms = bomMasterService.findByProjectId(projectId);

        for (BomMaster bom : projectBoms) {
            // 2. 废弃BOM（如果需要）
            if (bom.getStatus() == StatusEnum.FQ.getCode()) { // 已发布状态
                bomMasterService.obsoleteBom(bom.getId(), "项目结束自动废弃");
            }
        }

        // 3. 设置项目关联关系失效日期
        bomProjectRelationService.batchExpireRelationsByProject(projectId, projectEndDate);

        log.info("项目结束处理完成: projectId={}", projectId);
    }

    /**
     * 完成BOM
     * @param request
     * @return
     */
    @Override
    public BomMaster completeBom(BomCreationRequest request) {
        return bomMasterService.completeBom(request);
    }

    /**
     * 删除bom信息
     * @param ids
     */
    @Override
    public void deleteBomByIds(List<Long> ids) {
        ids.forEach(id->{
            List<BomProjectRelation> relations = bomProjectRelationService.getRelationsByBomId(id);
            relations.forEach(r->{
                bomProjectRelationService.removeById(r.getId());
            });
            List<BomVersion> versions = bomVersionService.getVersionHistory(id);
            versions.forEach(v->{
                bomVersionService.removeById(v.getId());
            });

            List<BomStructure> structures = bomStructureService.getBomMaterialList(id);
            structures.forEach(s->{
                bomStructureService.deleteBomStructureItem(s.getId());
            });
            bomMasterService.removeById(id);
        });
    }

    /**
     * 提交bom任务时长
     * @param request
     * @return
     */
    @Override
    public BomMaster submitBomDays(BomCreationRequest request) {
        BomMaster master = bomMasterService.submitBomDays(request);
        return master;
    }

    /**
     * 应用结构调整
     */
    private void applyStructureAdjustments(Long bomVersionId, List<StructureAdjustment> adjustments) {
        for (StructureAdjustment adjustment : adjustments) {
            switch (adjustment.getAdjustmentType()) {
                case "UPDATE_QUANTITY":
                    // 更新用量
                    updateItemQuantity(bomVersionId, adjustment);
                    break;
                case "UPDATE_SUPPLIER":
                    // 更新供应商
                    updateItemSupplier(bomVersionId, adjustment);
                    break;
                case "ADD_ITEM":
                    // 新增物料
                    addNewItem(bomVersionId, adjustment);
                    break;
                case "REMOVE_ITEM":
                    // 移除物料
                    removeItem(bomVersionId, adjustment);
                    break;
            }
        }
    }

    /**
     * 添加额外物料项
     */
    private void addAdditionalItems(Long bomVersionId, List<BomStructureRequest> additionalItems) {
        for (BomStructureRequest item : additionalItems) {
            BomStructure structure = new BomStructure();
            BeanUtils.copyProperties(item,structure);
            structure.setBomVersionId(bomVersionId);
            bomStructureService.addBomStructureItem(structure);
        }
    }

    /**
     * 更新供应商信息
     */
    private void updateSupplierInformation(Long bomVersionId, List<SupplierUpdate> supplierUpdates) {
        for (SupplierUpdate update : supplierUpdates) {
            bomStructureService.updateSupplierInfo(
                bomVersionId,
                update.getItemId(),
                update.getSupplierId(),
                update.getSupplierName()
            );
        }
    }

    /**
     * 触发变更后续动作
     */
    private void triggerPostChangeActions(Long changeLogId) {
        log.info("触发变更后续动作: changeLogId={}", changeLogId);

        try {
            BomChangeLog changeLog = bomChangeLogService.getById(changeLogId);
            if (changeLog == null) {
                log.warn("变更记录不存在: changeLogId={}", changeLogId);
                return;
            }

            // 1. 通知相关部门
            notifyRelatedDepartments(changeLog);

            // 2. 更新缓存
            updateRelatedCache(changeLog);

            // 3. 重新计算MRP（如果是制造BOM）
            if (isMbomChange(changeLog)) {
                triggerMrpRecalculation(changeLog.getBomId());
            }

            // 4. 更新采购计划
            if (isSupplierRelatedChange(changeLog)) {
                updatePurchasingPlan(changeLog);
            }

            // 5. 发送变更通知邮件
            sendChangeNotification(changeLog);

        } catch (Exception e) {
            log.error("执行变更后续动作失败: changeLogId={}", changeLogId, e);
        }
    }

    /**
     * 通知相关部门
     */
    private void notifyRelatedDepartments(BomChangeLog changeLog) {
        scheduledExecutorService.schedule(() -> {
            SseMessageDto dto = new SseMessageDto();
            dto.setMessage("BOM信息变更！");
            dto.setUserIds(List.of(LoginHelper.getUserId()));
            SseMessageUtils.publishMessage(dto);
        }, 5, TimeUnit.SECONDS);
    }


    /**
     * 更新相关缓存
     */
    private void updateRelatedCache(BomChangeLog changeLog) {
        log.info("更新相关缓存: bomId={}", changeLog.getBomId());
        // 这里可以清理或更新Redis缓存
        // 例如：redisTemplate.delete("bom:structure:" + changeLog.getBomId());
    }

    /**
     * 判断是否为制造BOM变更
     */
    private boolean isMbomChange(BomChangeLog changeLog) {
        BomMaster bomMaster = bomMasterService.getById(changeLog.getBomId());
        return bomMaster != null && bomMaster.getBomType() == 3; // 制造BOM
    }

    /**
     * 触发MRP重新计算
     */
    private void triggerMrpRecalculation(Long bomId) {
        log.info("触发MRP重新计算: bomId={}", bomId);
        // 这里可以异步触发MRP重新计算
        //mrpService.recalculate(bomId);
    }

    /**
     * 判断是否为供应商相关变更
     */
    private boolean isSupplierRelatedChange(BomChangeLog changeLog) {
        try {
            String changeContent = changeLog.getChangeContent();
            return changeContent != null && (
                changeContent.contains("supplier") ||
                    changeContent.contains("供应商") ||
                    changeContent.contains("unitPrice") ||
                    changeContent.contains("单价")
            );
        } catch (Exception e) {
            log.warn("判断供应商相关变更失败", e);
            return false;
        }
    }

    /**
     * 更新采购计划
     */
    private void updatePurchasingPlan(BomChangeLog changeLog) {
        log.info("更新采购计划: bomId={}", changeLog.getBomId());
        // 这里可以更新采购计划
        //purchaseInService.updateByBo(changeLog);
    }

    /**
     * 发送变更通知邮件
     */
    private void sendChangeNotification(BomChangeLog changeLog) {
        log.info("发送变更通知邮件: changeLogId={}", changeLog.getId());
        // 这里可以发送邮件通知
    }

    /**
     * 更新物料用量
     */
    private void updateItemQuantity(Long bomVersionId, StructureAdjustment adjustment) {
        log.info("更新物料用量: bomVersionId={}, itemId={}, newQuantity={}",
            bomVersionId, adjustment.getItemId(), adjustment.getNewQuantity());

        try {
            List<BomStructure> structures = bomStructureService.getBomMaterialList(bomVersionId)
                .stream()
                .filter(s -> s.getItemId().equals(adjustment.getItemId()))
                .collect(ArrayList::new, (list, item) -> list.add(item), ArrayList::addAll);

            for (BomStructure structure : structures) {
                structure.setQuantity(adjustment.getNewQuantity());
                structure.setRemark(structure.getRemark() + " [用量调整: " + adjustment.getRemark() + "]");
                bomStructureService.updateBomStructureItem(structure);
            }

            log.info("物料用量更新完成，共更新{}条记录", structures.size());

        } catch (Exception e) {
            log.error("更新物料用量失败", e);
            throw new RuntimeException("更新物料用量失败: " + e.getMessage());
        }
    }

    /**
     * 更新供应商信息
     */
    private void updateItemSupplier(Long bomVersionId, StructureAdjustment adjustment) {
        log.info("更新物料供应商: bomVersionId={}, itemId={}, newSupplierId={}",
            bomVersionId, adjustment.getItemId(), adjustment.getNewSupplierId());

        try {
            bomStructureService.updateSupplierInfo(
                bomVersionId,
                adjustment.getItemId(),
                adjustment.getNewSupplierId(),
                adjustment.getNewSupplierName()
            );

            // 同时更新单价（如果提供）
            if (adjustment.getNewUnitPrice() != null) {
                bomStructureService.updateItemPrice(
                    bomVersionId,
                    adjustment.getItemId(),
                    adjustment.getNewUnitPrice()
                );
            }

            log.info("物料供应商信息更新完成");

        } catch (Exception e) {
            log.error("更新物料供应商失败", e);
            throw new RuntimeException("更新物料供应商失败: " + e.getMessage());
        }
    }

    /**
     * 新增物料项
     */
    private void addNewItem(Long bomVersionId, StructureAdjustment adjustment) {
        log.info("新增物料项: bomVersionId={}, itemCode={}",
            bomVersionId, adjustment.getItemCode());

        try {
            BomStructure structure = new BomStructure();
            structure.setBomVersionId(bomVersionId);
            structure.setItemId(adjustment.getItemId());
            structure.setItemCode(adjustment.getItemCode());
            structure.setItemName(adjustment.getItemName());
            structure.setQuantity(adjustment.getNewQuantity());
            structure.setSupplierId(adjustment.getNewSupplierId());
            structure.setSupplierName(adjustment.getNewSupplierName());
            structure.setUnitPrice(adjustment.getNewUnitPrice());
            structure.setRemark("结构调整新增: " + adjustment.getRemark());

            bomStructureService.addBomStructureItem(structure);

            log.info("新增物料项完成: structureId={}", structure.getId());

        } catch (Exception e) {
            log.error("新增物料项失败", e);
            throw new RuntimeException("新增物料项失败: " + e.getMessage());
        }
    }

    /**
     * 移除物料项
     */
    private void removeItem(Long bomVersionId, StructureAdjustment adjustment) {
        log.info("移除物料项: bomVersionId={}, itemId={}",
            bomVersionId, adjustment.getItemId());

        try {
            List<BomStructure> structures = bomStructureService.getBomMaterialList(bomVersionId)
                .stream()
                .filter(s -> s.getItemId().equals(adjustment.getItemId()))
                .collect(ArrayList::new, (list, item) -> list.add(item), ArrayList::addAll);

            for (BomStructure structure : structures) {
                bomStructureService.deleteBomStructureItem(structure.getId());
            }

            log.info("移除物料项完成，共移除{}条记录", structures.size());

        } catch (Exception e) {
            log.error("移除物料项失败", e);
            throw new RuntimeException("移除物料项失败: " + e.getMessage());
        }
    }

    /**
     * 生成MRP物料需求计划 - 增强版
     */
    public MrpResult generateMrpEnhanced(MrpRequest request) {
        log.info("生成增强版MRP: bomId={}, productionQuantity={}",
            request.getBomId(), request.getProductionQuantity());

        try {
            // 1. 获取有效的制造BOM版本
            BomVersion bomVersion = bomVersionService.getCurrentVersion(request.getBomId());
            if (bomVersion == null) {
                throw new RuntimeException("找不到有效的BOM版本");
            }

            // 2. 展开BOM结构
            List<BomStructure> bomStructures = bomStructureService.getBomMaterialList(bomVersion.getId());

            // 3. 计算物料需求
            List<MaterialRequirement> requirements = new ArrayList<>();

            for (BomStructure structure : bomStructures) {
                MaterialRequirement requirement = calculateMaterialRequirement(structure, request);
                requirements.add(requirement);
            }

            // 4. 合并相同物料的需求
            Map<Long, MaterialRequirement> mergedRequirements = mergeSameMaterialRequirements(requirements);

            // 5. 排序（按交货日期和优先级）
            List<MaterialRequirement> sortedRequirements = new ArrayList<>(mergedRequirements.values());
            sortedRequirements.sort(Comparator.comparing(MaterialRequirement::getRequiredDate)
                .thenComparing(r -> r.getSupplierName() != null ? r.getSupplierName() : ""));

            MrpResult result = new MrpResult();
            result.setRequirements(sortedRequirements);
            result.setSuccess(true);
            result.setMessage("MRP生成成功，共" + sortedRequirements.size() + "种物料");

            log.info("增强版MRP生成成功，共{}种物料", sortedRequirements.size());
            return result;

        } catch (Exception e) {
            log.error("增强版MRP生成失败", e);
            MrpResult result = new MrpResult();
            result.setSuccess(false);
            result.setMessage("生成失败: " + e.getMessage());
            return result;
        }
    }

    /**
     * 计算单个物料需求
     */
    private MaterialRequirement calculateMaterialRequirement(BomStructure structure, MrpRequest request) {
        MaterialRequirement requirement = new MaterialRequirement();
        requirement.setItemId(structure.getItemId());
        requirement.setItemCode(structure.getItemCode());
        requirement.setItemName(structure.getItemName());
        requirement.setUnit(structure.getUnit());

        // 计算净需求量（考虑损耗率）
        BigDecimal scrapRate = structure.getScrapRate() != null ? structure.getScrapRate() : BigDecimal.ZERO;
        BigDecimal actualQuantity = structure.getQuantity()
            .multiply(request.getProductionQuantity())
            .multiply(BigDecimal.ONE.add(scrapRate.divide(new BigDecimal("100"))));

        requirement.setGrossRequirement(actualQuantity);
        requirement.setNetRequirement(actualQuantity); // 简化处理，实际应减去库存

        requirement.setSupplierId(structure.getSupplierId());
        requirement.setSupplierName(structure.getSupplierName());
        requirement.setLeadTime(structure.getLeadTime());

        // 计算需求日期
        Calendar cal = Calendar.getInstance();
        cal.setTime(request.getRequiredDate());
        if (structure.getLeadTime() != null) {
            cal.add(Calendar.DAY_OF_MONTH, -structure.getLeadTime());
        }
        requirement.setRequiredDate(cal.getTime());

        // 设置状态
        requirement.setStatus(structure.getIsKeyItem() == 1 ? "关键物料" : "普通物料");

        return requirement;
    }

    /**
     * 合并相同物料的需求
     */
    private Map<Long, MaterialRequirement> mergeSameMaterialRequirements(List<MaterialRequirement> requirements) {
        Map<Long, MaterialRequirement> mergedMap = new HashMap<>();

        for (MaterialRequirement req : requirements) {
            Long itemId = req.getItemId();

            if (mergedMap.containsKey(itemId)) {
                MaterialRequirement existing = mergedMap.get(itemId);

                // 合并数量
                existing.setGrossRequirement(existing.getGrossRequirement().add(req.getGrossRequirement()));
                existing.setNetRequirement(existing.getNetRequirement().add(req.getNetRequirement()));

                // 保留最早的需求日期
                if (req.getRequiredDate().before(existing.getRequiredDate())) {
                    existing.setRequiredDate(req.getRequiredDate());
                }

                // 更新状态（如果有关键物料则标记为关键）
                if ("关键物料".equals(req.getStatus())) {
                    existing.setStatus("关键物料");
                }

            } else {
                mergedMap.put(itemId, req);
            }
        }

        return mergedMap;
    }

    /**
     * 批量处理BOM变更
     */
    @Transactional
    public Map<String, Object> batchProcessBomChanges(List<Long> changeLogIds, Long operatorId, String operatorName) {
        log.info("批量处理BOM变更: changeLogIds={}, operatorId={}", changeLogIds, operatorId);

        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errors = new ArrayList<>();

        for (Long changeLogId : changeLogIds) {
            try {
                bomChangeLogService.implementChange(changeLogId);
                triggerPostChangeActions(changeLogId);
                successCount++;
            } catch (Exception e) {
                failCount++;
                errors.add("变更记录" + changeLogId + "处理失败: " + e.getMessage());
                log.error("批量处理BOM变更失败: changeLogId={}", changeLogId, e);
            }
        }

        result.put("totalCount", changeLogIds.size());
        result.put("successCount", successCount);
        result.put("failCount", failCount);
        result.put("errors", errors);
        result.put("success", failCount == 0);
        result.put("message", String.format("批量处理完成，成功%d条，失败%d条", successCount, failCount));

        log.info("批量处理BOM变更完成: 总数={}, 成功={}, 失败={}",
            changeLogIds.size(), successCount, failCount);

        return result;
    }

    /**
     * 获取BOM变更影响分析
     */
    public Map<String, Object> getBomChangeImpactAnalysis(Long bomId, BomChangeRequest changeRequest) {
        log.info("分析BOM变更影响: bomId={}, changeType={}", bomId, changeRequest.getChangeType());

        Map<String, Object> analysis = new HashMap<>();

        try {
            // 1. 基本影响信息
            analysis.put("bomId", bomId);
            analysis.put("changeType", changeRequest.getChangeType());
            analysis.put("changeObject", changeRequest.getChangeObject());

            // 2. 成本影响分析
            BigDecimal costImpact = analyzeCostImpact(bomId, changeRequest);
            analysis.put("costImpact", costImpact);

            // 3. 供应链影响分析
            List<String> supplierImpacts = analyzeSupplierImpact(bomId, changeRequest);
            analysis.put("supplierImpacts", supplierImpacts);

            // 4. 生产影响分析
            List<String> productionImpacts = analyzeProductionImpact(bomId, changeRequest);
            analysis.put("productionImpacts", productionImpacts);

            // 5. 风险评估
            String riskLevel = assessChangeRisk(changeRequest);
            analysis.put("riskLevel", riskLevel);

            // 6. 建议措施
            List<String> recommendations = generateRecommendations(changeRequest);
            analysis.put("recommendations", recommendations);

            analysis.put("analysisTime", new Date());
            analysis.put("success", true);

        } catch (Exception e) {
            log.error("BOM变更影响分析失败", e);
            analysis.put("success", false);
            analysis.put("error", e.getMessage());
        }

        return analysis;
    }

    private BigDecimal analyzeCostImpact(Long bomId, BomChangeRequest changeRequest) {
        // 简化的成本影响分析
        return BigDecimal.ZERO;
    }

    private List<String> analyzeSupplierImpact(Long bomId, BomChangeRequest changeRequest) {
        List<String> impacts = new ArrayList<>();
        impacts.add("可能需要重新评估供应商资质");
        impacts.add("可能影响采购周期和成本");
        return impacts;
    }

    private List<String> analyzeProductionImpact(Long bomId, BomChangeRequest changeRequest) {
        List<String> impacts = new ArrayList<>();
        impacts.add("可能需要调整生产工艺");
        impacts.add("可能影响生产计划和排程");
        return impacts;
    }

    private String assessChangeRisk(BomChangeRequest changeRequest) {
        // 根据变更类型评估风险等级
        switch (changeRequest.getChangeType()) {
            case 1: return "中等风险";
            case 2: return "低风险";
            case 3: return "高风险";
            case 4: return "极高风险";
            default: return "未知风险";
        }
    }

    private List<String> generateRecommendations(BomChangeRequest changeRequest) {
        List<String> recommendations = new ArrayList<>();
        recommendations.add("建议提前通知相关部门");
        recommendations.add("建议进行充分的测试验证");
        recommendations.add("建议制定应急预案");
        return recommendations;
    }
}
